﻿using Microsoft.Xna.Framework;
using OTAPI.Tile;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using Terraria;
using Terraria.ID;
using TShockAPI;

namespace TShock_IslandWar
{
    internal class TileCollection : ITileCollection
    {
        protected ITile[,] _tiles;

        public int Width => this._tiles.GetLength(0);

        public int Height => this._tiles.GetLength(1);

        private static ITile[,] GetNewTileCollection()
        {
            DynamicMethod dynamicMethod = new DynamicMethod(nameof(GetNewTileCollection), typeof(ITile[,]), (Type[])null);
            ILGenerator ilGenerator = dynamicMethod.GetILGenerator();
            ilGenerator.Emit(OpCodes.Ldsfld, typeof(Main).GetField("maxTilesX"));
            ilGenerator.Emit(OpCodes.Ldsfld, typeof(Main).GetField("maxTilesY"));
            ilGenerator.Emit(OpCodes.Newobj, ((IEnumerable<ConstructorInfo>)typeof(Terraria.Tile[,]).GetConstructors()).Single<ConstructorInfo>((Func<ConstructorInfo, bool>)(x => x.GetParameters().Length == 2)));
            ilGenerator.Emit(OpCodes.Ret);
            return (ITile[,])dynamicMethod.Invoke((object)null, (object[])null);
        }

        internal TileCollection()
          : this(TileCollection.GetNewTileCollection())
        {
        }

        protected TileCollection(ITile[,] collection) => this._tiles = collection;

        public virtual ITile this[int x, int y]
        {
            get => this._tiles[x, y];
            set => this._tiles[x, y] = value;
        }
    }

    class DefaultWorld
    {
        public ITileCollection DefaultTile = new TileCollection();
        private Chest[] DefaultChest = new Chest[Main.chest.Length];
        private Sign[] DefaultSign = new Sign[Main.sign.Length];

        private static List<Vector2> BedPosition = new List<Vector2>();

        public Vector2 redSpawn = Vector2.Zero;
        public Vector2 blueSpawn = Vector2.Zero;
        public Vector2 defalueSpawn = Vector2.Zero;
        public List<int[]> itemSpawn;
        public DefaultWorld(Config config)
        {
            defalueSpawn = new Vector2(Main.spawnTileX, Main.spawnTileY);
            itemSpawn = new List<int[]>();

            for (int y = 0; y < Main.maxTilesY; y++)
            {
                for (int x = 0; x < Main.maxTilesX; x++)
                {
                    ITile tile = (ITile)Main.tile[x, y].Clone();
                    DefaultTile[x, y] = tile;
                    if (tile == null)
                    {
                        continue;
                    }
                    if (tile.active() && tile.type == config.RedSpawnTile)
                    {
                        redSpawn = new Vector2(x, y);
                    }
                    else if(tile.active() && tile.type == config.BlueSpawnTile)
                    {
                        blueSpawn = new Vector2(x, y);
                    }
                    else if (tile.active() && tile.type == config.BedTile)
                    {
                        BedPosition.Add(new Vector2(x, y));
                    }
                    else
                    {
                        for (int i = 0; i < config.ItemWallGenerator.Count; i++)
                        {
                            var tileID = config.ItemWallGenerator[i][0];
                            var itemID = config.ItemWallGenerator[i][1];
                            var number = config.ItemWallGenerator[i][2];
                            var interval = config.ItemWallGenerator[i][3];
                            if (tileID != tile.wall)
                                    continue;
                            itemSpawn.Add(new int[] {x * 16,y * 16,itemID,number,interval,0});
                            Console.WriteLine("[{2}]资源点:{0},{1}", x, y,itemID);
                            break;
                        }
                    }
                }
            }
            for (int i = 0; i < Main.chest.Length; i++)
            {
                Chest chest = null;
                if (Main.chest[i] == null)
                {
                    chest = null;
                }
                else
                {
                    chest = (Chest)Main.chest[i].Clone();
                    Item[] items = new Item[40];
                    for (int j = 0; j < 40; j++)
                    {
                        items[j] = chest.item[j].DeepClone();
                    }
                    chest.item = items;
                }
                DefaultChest[i] = chest;
            }
            for (int i = 0; i < Main.sign.Length; i++)
            {
                Sign sign;
                if (Main.sign[i] == null)
                {
                    sign = null;
                }
                else
                {
                    sign = new Sign();
                    sign.x = Main.sign[i].x;
                    sign.y = Main.sign[i].y;
                    sign.text = Main.sign[i].text;
                }
                DefaultSign[i] = sign;
            }
            
            
            if (redSpawn == null || blueSpawn == null)
            {
                throw new Exception("未设置出生点");
            }
            TShock.Log.ConsoleInfo("红队的出生点设定为:{0}",redSpawn);
            TShock.Log.ConsoleInfo("蓝队的出生点设定为:{0}",blueSpawn);
        }
        public void Reset()
        {
            for (int y = 0; y < Main.maxTilesY; y++)
            {
                for (int x = 0; x < Main.maxTilesX; x++)
                {
                    Main.tile[x, y] = (ITile)DefaultTile[x, y].Clone();
                }
            }
            for (int i = 0; i < DefaultChest.Length; i++)
            {
                if (DefaultChest[i] == null)
                {
                    continue;
                }
                Chest chest = (Chest)DefaultChest[i].Clone();
                Item[] items = new Item[40];
                for (int j = 0; j < 40; j++)
                {
                    items[j] = chest.item[j].DeepClone();
                }
                chest.item = items;
                Main.chest[i] = chest;
            }

            for (int i = 0; i < Main.sign.Length; i++)
            {
                if (DefaultSign[i] != null)
                {
                    if (Main.sign[i] == null)
                    {
                        Main.sign[i] = new Sign();
                    }
                    Main.sign[i].x = DefaultSign[i].x;
                    Main.sign[i].y = DefaultSign[i].y;
                    Main.sign[i].text = DefaultSign[i].text;
                }
            }


            foreach (TSPlayer person in TShock.Players)
            {
                if ((person != null) && (person.Active))
                {
                    for (int i = 0; i < 255; i++)
                    {
                        for (int j = 0; j < Main.maxSectionsX; j++)
                        {
                            for (int k = 0; k < Main.maxSectionsY; k++)
                            {
                                Netplay.Clients[i].TileSections[j, k] = false;
                            }
                        }
                    }
                }
            }
        }
    }
}
